package blue.http.ext.internal.core.filter;

import blue.base.core.util.NumberUtil;
import blue.http.core.annotation.Filter;
import blue.http.core.filter.HttpFilter;
import blue.http.core.message.HttpRequest;
import blue.http.core.message.HttpResponse;
import io.prometheus.client.Histogram;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

/**
 * @author Jin Zheng
 * @since 1.0 2020-01-09
 */
@Filter(filters = "/**", excludes = "/management/**", order = Integer.MAX_VALUE - 1)
public class MonitorFilter implements HttpFilter {
	private static Logger logger = LoggerFactory.getLogger(MonitorFilter.class);
	private static final double[] BUCKETS = {5, 10, 50, 100, 150, 200, 500, 1000, 2000, 5000};

	private ThreadLocal<Long> startLocal = new ThreadLocal<>();
	private Histogram histogram;

	public MonitorFilter() {
		this.init(BUCKETS);
	}

	public MonitorFilter(String buckets) {
		if (buckets == null || buckets.isEmpty()) {
			this.init(BUCKETS);
		} else {
			this.init(NumberUtil.splitDouble(buckets));
		}
	}

	public MonitorFilter(double...buckets) {
		this.init(buckets);
	}

	private void init(double...buckets) {
		this.histogram = Histogram.build("summary_http_request", "Http Request Latency Summary")
				.labelNames("path", "method", "code")
				.buckets(buckets)
				.register();
		logger.info("Initialize MonitorFilter, label: path, method, code, buckets: {}", Arrays.toString(buckets));
	}

	@Override
	public boolean preHandle(HttpRequest request, HttpResponse response) throws Exception {
		startLocal.set(System.currentTimeMillis());
		return true;
	}

	@Override
	public void afterCompletion(HttpRequest request, HttpResponse response, Exception ex) throws Exception {
		long start = startLocal.get();
		startLocal.remove();
		long used = System.currentTimeMillis() - start;
		int code = response.getHttpStatus() == null ? 200 : response.getHttpStatus().code();
		histogram.labels(request.getUrl(), request.getHttpMethod().name(), String.valueOf(code))
				.observe(used / 1000.0d);
	}
}
